<template>
  <div>
    <ZgDialog
      :width="view.width"
      :top="view.top"
      :title="view.title"
      :showFooter="showFooter"
      v-model="visible"
      @ok="save">
      <a-empty v-if="!columns||columns.length===0" description="没有找到视图数据"></a-empty>
      <div v-else>
        <div class="wfull flx-c fs24 fw8 mb15" v-if="showTitle">{{ title }}</div>
        <div :style="{ padding: `${layout.视图边距}px` }">
          <a-row :gutter="layout.左右间距">
            <template v-for="(c, i) in columns">
              <a-col v-if="c.divider && c.divider.length > 0" :span="24" :key="`column_bar${i}`">
                <a-divider>{{ c.divider }}</a-divider>
              </a-col>
              <a-col v-if="c.isShow" :offset="c.offset" :span="c.span" :key="`column${i}`">
                <div :class="layout.标签对齐==='top'?'':'flx-s'" :style="{marginBottom:`${layout.上下间距}px`}">
                  <div :class="layout.标签对齐==='right'?'tar':'tal'" class="mr10" :style="{width:`${layout.标签宽度}px`}">
                    <span class="mr5 error" v-if="c.isNeed">*</span>{{ c.name }}
                  </div>
                  <div class="flx-1" :class="layout.标签对齐 === 'top' ? 'mt10' : ''">
                    <div v-if="obj !== null">
                      <div class="flx-s">
                        <div v-if="c.compType === '文本'">{{ c.defaultVal }}</div>
                        <div v-if="c.compType === '单行文本'" class="wfull">
                          <div class="flx-s wfull" v-if="c.extra && c.extra.suffix === 'btn'">
                            <ZgInput
                              :disabled="c.disabled"
                              v-model="obj[c.code]"
                              :placeholder="(c.extra && c.extra.placeholder) || ''"
                              :maxLength="c.extra && c.extra.maxLength"
                            >
                            </ZgInput>
                            <ZgButton class="ml10" :icon="c.extra.icon" @click="inputClick(obj)">{{
                              c.extra.btn
                            }}</ZgButton>
                          </div>
                          <ZgInput
                            v-else
                            :disabled="c.disabled"
                            v-model="obj[c.code]"
                            :placeholder="(c.extra && c.extra.placeholder) || ''"
                            :maxLength="c.extra && c.extra.maxLength"
                          >
                            <div slot="suffix" v-if="c.extra && c.extra.suffix === 'icon'">
                              <i class="cpt fa" :class="`fa-${c.extra.icon}`" @click="inputClick(obj)" />
                            </div>
                          </ZgInput>
                        </div>
                        <ZgSelect
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '下拉选择'"
                          :options="c.extra.下拉选项"
                        ></ZgSelect>
                        <ZgRadio
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '单选'"
                          :options="c.extra.选项"
                        ></ZgRadio>
                        <ZgNumber :disabled="c.disabled" v-model="obj[c.code]" v-if="c.compType === '整数'"></ZgNumber>
                        <ZgNumber
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '浮点数'"
                          isFloat
                        ></ZgNumber>
                        <ZgCheckbox
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '单选框'"
                        ></ZgCheckbox>
                        <ZgMultiple
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '多选'"
                          :code="c.extra.字典类型"
                        ></ZgMultiple>
                        <ZgDatePicker
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '日期'"
                        ></ZgDatePicker>
                        <ZgDateTimePicker
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '日期时间'"
                        ></ZgDateTimePicker>
                        <ZgDictionary
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '字典'"
                          :code="c.extra.字典类型"
                        ></ZgDictionary>
                        <ZgSwitch :disabled="c.disabled" v-model="obj[c.code]" v-if="c.compType === '开关'"></ZgSwitch>
                        <ZgTextarea
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '多行文本'"
                          :rows="parseInt(c.extra.行数)"
                          :maxLength="c.extra && c.extra.maxLength"
                          class="mb15"
                        ></ZgTextarea>
                        <ZgTinymce
                          v-model="obj[c.code]"
                          v-if="c.compType === '富文本'"
                          :height="parseInt(c.extra.高度)"
                        ></ZgTinymce>
                        <ZgUpImg v-model="obj[c.code]" v-if="c.compType === '图片'"></ZgUpImg>
                        <ZgKeyValue v-model="other[c.code + '_kv']" v-if="c.compType === '键值对'"></ZgKeyValue>
                        <ZgPassword
                          :disabled="c.disabled"
                          v-model="obj[c.code]"
                          v-if="c.compType === '密码'"
                        ></ZgPassword>
                        <ZgUpImgs v-model="obj[c.code]" v-if="c.compType === '多图'" :note="c.extra.note"></ZgUpImgs>
                        <div v-if="c.unit" class="ml10">{{ c.unit }}</div>
                      </div>
                      <div v-if="c.note && c.note.length > 0" class="info fs10 mt5">
                        {{ c.note }}
                      </div>
                    </div>
                  </div>
                </div>
              </a-col>
            </template>
          </a-row>
        </div>
      </div>
    </ZgDialog>
  </div>
</template>
<script>
export default {
  props: {
    inputClick: {
      type: Function,
      default: (t) => {}
    },
    beforeSubmit: {
      type: Function,
      default: (t) => {
        return {
          ok: true,
          msg: ''
        }
      }
    },
    view: {
      type: Object,
      default: () => {
        return { width: '60%', top: '5%', title: '添加数据' }
      }
    },
    title: {
      type: String,
      default: ''
    },
    showTitle: {
      type: Boolean,
      default: false
    },
    param: {
      type: Object,
      default: () => {
        return {}
      }
    },
    layout: {
      type: Object,
      default: () => {
        return { 视图边距: 10, 标签宽度: 120, 标签对齐: 'right', 左右间距: 10, 上下间距: 10 }
      }
    },
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    formulas: {
      type: Array,
      default: () => {
        return [
          { triggerMode: '初始化时', name: '公式1', content: 'console.log("init");' },
          { triggerMode: '数据变化时', name: '公式2', content: 'console.log("update");' },
          { triggerMode: '提交时', name: '公式3', content: 'console.log("submit");' }
        ]
      }
    },
    validUrl: {
      type: String,
      default: ''
    },
    saveUrl: {
      type: String,
      default: ''
    },
    showFooter: {
      type: Boolean,
      default: true
    },
    setColumnKey: {
      type: Function,
      default: function (param) {
        return param
      }
    }
  },
  data() {
    return {
      visible: false,
      obj: null,
      other: {}
    }
  },
  watch: {
    obj: {
      handler (newVal, oldVal) {
        this.setColumnKey(newVal)
        if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
          console.log('数据变化时执行公式')
          this.doFormula(
            this.formulas.filter((t) => {
              return t.triggerMode === '数据变化时'
            })
          )
        }
      },
      deep: true
    }
  },
  mounted() {
    this.initData()
  },
  methods: {
    open(json) {
      this.obj = Object.assign({}, this.obj, json || {})
      this.visible = true
    },
    doFormula(formulas) {
      if (!formulas || formulas.length === 0) {
        return
      }
      const arr = []
      formulas.forEach((t) => {
        try {
          // eslint-disable-next-line no-eval
          eval(t.content)
        } catch (e) {
          arr.push(t)
        }
      })
      if (arr.length > 0) {
        this.$error({ title: `有${arr.length}个公式执行错误：${arr.map((t) => t.name).join('、')}` })
        return false
      } else {
        return true
      }
    },
    initData() {
      // 初始化默认值
      const result = {}
      this.columns.forEach((item) => {
        if (item.compType === '键值对') {
          this.other[item.code + '_kv'] = JSON.parse(item.defaultVal)
        }
        // 判断是否存在 isShow 属性
        if (!item.hasOwnProperty('isShow')) {
          item.isShow = true
        }
        result[item.code] = item.defaultVal
      })

      this.obj = result
      console.log('初始化时执行公式')
      this.doFormula(
        this.formulas.filter((t) => {
          return t.triggerMode === '初始化时'
        })
      )
    },
    save() {
      // 验证接口设置
      if (this.saveUrl.length === 0) {
        this.$error({ title: `未设置保存接口` })
        return
      }
      // 验证字段
      if (this.columns.length === 0) {
        this.$error({ title: `没有字段信息` })
        return
      }
      // 先给特殊类型赋值
      for (const i in this.columns) {
        const column = this.columns[i]
        if (column.compType === '键值对') {
          const result = this.other[column.code + '_kv']
          const step1Arr = result.filter((t) => {
            return t.key.length > 0 && t.value.length > 0
          })
          const step2Arr = []
          step1Arr.forEach((t1) => {
            if (step2Arr.some((t2) => t2.key === t1.key)) {
              console.log(t1.key + '重复')
            } else {
              step2Arr.push({ key: t1.key, value: t1.value })
            }
          })

          this.obj[column.code] = JSON.stringify(step2Arr)
        }
      }
      // 验证必填项
      for (const i in this.columns) {
        const column = this.columns[i]
        const value = this.obj[column.code]
        if (!column.isNeed) {
          continue
        }
        if (['单选框', '开关'].includes(column.compType)) {
          continue
        } else if (['整数', '浮点数'].includes(column.compType)) {
          if (!value || value === 0) {
            this.$error({ title: `${column.name}不能为0` })
            return
          }
        } else if (['键值对'].includes(column.compType)) {
          if (!value || value === 0 || JSON.parse(value).length === 0) {
            this.$error({ title: `${column.name}为必填项` })
            return
          }
        } else {
          if (!value || value.length === 0) {
            this.$error({ title: `${column.name}为必填项` })
            return
          }
        }
      }
      // 验证正则，只验证单行文本
      for (const i in this.columns) {
        const column = this.columns[i]
        const value = this.obj[column.code]
        if (column.compType === '单行文本' && column.regex && column.regex.length > 0) {
          const reg = new RegExp(column.regex)
          if (!reg.test(value)) {
            this.$error({ title: column.errorMsg })
            return
          }
        }
      }

      // 验证密码
      for (const i in this.columns) {
        const column = this.columns[i]
        const value = this.obj[column.code]
        if (column.compType === '密码') {
          if (!this.checkPwd(value)) {
            this.$error({
              title: column.name + '不符合格式要求，密码长度必须大于或等于12位，且包含数字、大小写字母及特殊字符'
            })
            return
          }
        }
      }

      // 提交前执行公式
      console.log('提交前执行公式')
      this.doFormula(
        this.formulas.filter((t) => {
          return t.triggerMode === '提交时'
        })
      )
      const param = Object.assign({}, this.param, this.obj)
      // beforeSubmit
      if (this.beforeSubmit) {
        const res = this.beforeSubmit(param)
        if (!res.ok) {
          this.$error({ title: res.msg })
          return
        }
      }
      // 远程验证接口
      if (this.validUrl && this.validUrl.length > 0) {
        this.$http.post(
          this.validUrl,
          param,
          () => {
            this.realSave(param)
          },
          (exp) => {
            console.log('remote-valid-exp', exp)
            this.$error({ title: '远程验证接口调用失败，请检查接口地址' })
          }
        )
      } else {
        this.realSave(param)
      }
    },
    realSave(param) {
      this.$http.post(this.saveUrl, param, () => {
        this.visible = false
        this.$emit('ok')
      })
    }
  }
}
</script>

<style lang="scss" scoped></style>
